<!--
Copyright (c) 2009 The Chromium Authors. All rights reserved.
Use of this source code is governed by a BSD-style license that can be
found in the LICENSE file.
 -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
  "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta charset="utf-8">
<title>WebGL Big FBO Test</title>
<link rel="stylesheet" href="../resources/js-test-style.css"/>
<script src="../resources/desktop-gl-constants.js" type="text/javascript"></script>
<script src="../../debug/webgl-debug.js"></script>
<script src="../resources/js-test-pre.js"></script>
<script src="../conformance/resources/webgl-test.js"></script>
</head>
<body>
<div id="description"></div>
<div id="console"></div>
<script id="vshader" type="x-shader/x-vertex">
attribute vec4 vPosition;
attribute vec2 texCoord0;
uniform mat4 world;
varying vec2 texCoord;
void main()
{
    gl_Position = vPosition * world;
    texCoord = texCoord0;
}
</script>

<script id="fshader" type="x-shader/x-fragment">
precision mediump float;
uniform sampler2D tex;
varying vec2 texCoord;
void main()
{
    gl_FragColor = texture2D(tex, texCoord);
}
</script>
<canvas id="canvas" width="1024" height="1024"> </canvas>
<script>
window.onload = init;
debug("Tests the performance of using lots of large FBOs");

function init() {
  if (confirm(
      "after clicking ok your machine may be come unresponsive or crash")) {
    main();
  } else {
    debug("cancelled");
  }
}

function main() {
  debug("");
  debug("Canvas.getContext");
  var g_worldLoc;
  var g_texLoc;
  var g_textures = [];
  gl = initWebGL("canvas", "vshader", "fshader", [ "vPosition", "texCoord0"], [ 0, 0, 0, 1 ], 1);
  if (!gl) {
    testFailed("context does not exist");
  } else {
    testPassed("context exists");

    debug("");
    debug("Checking for out of memory handling.");

    var size = gl.getParameter(gl.MAX_RENDERBUFFER_SIZE);
    debug("max render buffer size: " + size);
    size = size / 2;
    debug("size used: " + size);

    var allocateFramebuffers = true;
    var intervalId = 0;
    var count = 0;

    WebGLDebugUtils.init(gl);

    function createFBO() {
      var tex = gl.createTexture();
      gl.bindTexture(gl.TEXTURE_2D, tex);
      gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
      gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
      gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
      gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
      gl.texImage2D(gl.TEXTURE_2D,
                    0,                 // level
                    gl.RGBA,           // internalFormat
                    size,              // width
                    size,              // height
                    0,                 // border
                    gl.RGBA,           // format
                    gl.UNSIGNED_BYTE,  // type
                    null);             // data
      var fb = gl.createFramebuffer();
      gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
      gl.framebufferTexture2D(
          gl.FRAMEBUFFER,
          gl.COLOR_ATTACHMENT0,
          gl.TEXTURE_2D,
          tex,
          0);
      var status = gl.checkFramebufferStatus(gl.FRAMEBUFFER);
      if (status != gl.FRAMEBUFFER_COMPLETE) {
        testFailed("gl.checkFramebufferStatus() returned " + WebGLDebugUtils.glEnumToString(status));
        return;
      }
      var err = gl.getError();
      if (err != gl.NO_ERROR) {
        if (err != gl.OUT_OF_MEMORY) {
          testFailed("gl.getError returned " + err);
        }
        return;
      }
      return { fb: fb, tex: tex };
    }

    gl.disable(gl.DEPTH_TEST);

    var maxFBOs = 2;
    for (var ii = 0; ii < maxFBOs; ++ii) {
      createFBO();
      var t = createFBO();
      if (!t) {
        break;
      }
      tex = t.tex;
      fb = t.fb;

      gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
      gl.scissor(0, 0, size, size);
      gl.clearColor(0, ii / maxFBOs, 1 - ii / maxFBOs, 1);
      gl.clear(gl.COLOR_BUFFER_BIT);
      g_textures.push(tex);
    }

    debug("fbos allocated:" + g_textures.length);
    gl.scissor(0, 0, 1024, 1024);
    gl.bindFramebuffer(gl.FRAMEBUFFER, null);

    var vertexObject = gl.createBuffer();
    gl.bindBuffer(gl.ARRAY_BUFFER, vertexObject);
    gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
       -1,1,0, 1,1,0, -1,-1,0,
       -1,-1,0, 1,1,0, 1,-1,0
     ]), gl.STATIC_DRAW);
    gl.enableVertexAttribArray(0);
    gl.vertexAttribPointer(0, 3, gl.FLOAT, false, 0, 0);

    var vertexObject = gl.createBuffer();
    gl.bindBuffer(gl.ARRAY_BUFFER, vertexObject);
    gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([ 0,0, 1,0, 0,1,
       0,1, 1,0, 1,1
     ]), gl.STATIC_DRAW);
    gl.enableVertexAttribArray(1);
    gl.vertexAttribPointer(1, 2, gl.FLOAT, false, 0, 0);

    g_texLoc = gl.getUniformLocation(gl.program, "tex");
    gl.uniform1i(g_texLoc, 0);
    g_worldLoc = gl.getUniformLocation(gl.program, "world");
    gl.uniformMatrix4fv(g_worldLoc, false, [
       0, 0, 0, 0,
       0, 0, 0, 0,
       0, 0, 1, 0,
       0, 0, 0, 1]);

    setInterval(render, 1000/60);
  }

  var g_angle = 0;
  var g_texIndex = 0;
  function render() {
    g_angle += 0.1;
    g_texIndex++;
    if (g_texIndex >= g_textures.length) {
      g_texIndex = 0;
    }
    gl.bindTexture(gl.TEXTURE_2D, g_textures[g_texIndex]);
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
    gl.uniformMatrix4fv(g_worldLoc, false, rotationZ(g_angle));
    gl.clearColor(1,0,0,1);
    gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
    gl.drawArrays(gl.TRIANGLES, 0, 6);
  }
}

/**
 * Creates a 4-by-4 matrix which rotates around the z-axis by the given angle.
 * @param {number} angle The angle by which to rotate (in radians).
 * @return {!o3djs.math.Matrix4} The rotation matrix.
 */
function rotationZ(angle) {
  var c = Math.cos(angle);
  var s = Math.sin(angle);

  return [
    c, s, 0, 0,
    -s, c, 0, 0,
    0, 0, 1, 0,
    0, 0, 0, 1
  ];
};

debug("");
successfullyParsed = true;
</script>
<script>
</script>

</body>
</html>
